package com.nofx.mydemo.common.grayscale.aspect;

import com.google.gson.Gson;
import com.nofx.mydemo.common.grayscale.annotation.GrayScale;
import com.nofx.mydemo.common.grayscale.config.StarterService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.beanutils.BeanUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;

/**
 * 灰度切面
 * @author yyc-01407250
 * @date 2021年06月07日 11:29
 */
@Slf4j
@Aspect
@Component
public class GrayScaleProcessor {



    private final StarterService starterService;

    public GrayScaleProcessor(StarterService starterService) {
        System.out.println("启动配置注入成功");
        this.starterService = starterService;
    }


    @Around("@annotation(com.nofx.mydemo.common.grayscale.annotation.GrayScale)")
    public Object doRouter(ProceedingJoinPoint jp) throws  Throwable{
        Method method = getMethod(jp);
        GrayScale grayScale = method.getAnnotation(GrayScale.class);

        String keyValue = getFieldValue(grayScale.key(),jp.getArgs());
        log.info("bb grayscale handler method: {} value {}",method.getName(),keyValue);
        if(null == keyValue || "".equals(keyValue)){
            return jp.proceed();
        }

        String[] split = starterService.split(",");

        for(String str:split){
            if(keyValue.equals(str)){
                return jp.proceed();
            }
        }

        return returnObject(grayScale,method);


    }

    private Method getMethod(JoinPoint jp) throws NoSuchMethodException{
        Signature sig = jp.getSignature();
        ProceedingJoinPoint pjp;
        MethodSignature methodSignature = (MethodSignature) sig;
        return getClass(jp).getMethod(methodSignature.getName(),methodSignature.getParameterTypes());

    }

    private Class<? extends Object> getClass(JoinPoint jp) throws NoSuchMethodException{
        return jp.getTarget().getClass();
    }

    private Object returnObject(GrayScale grayScale,Method method) throws IllegalAccessException,InstantiationException{
        Class<?> returnType = method.getReturnType();
        String returnJson = grayScale.returnJson();
        if("".equals(returnJson)){
            return returnType.newInstance();
        }
        return new Gson().fromJson(returnJson,returnType);
    }

    private String getFieldValue(String field, Object[] args){
        String filedValue = null;
        for (Object arg:args){
            try {
                if(null == filedValue || "".equals(filedValue)){
                    filedValue = BeanUtils.getProperty(arg,field);
                }else {
                    break;
                }
            }catch (Exception e){
                if(args.length == 1){
                    return  args[0].toString();
                }
            }
        }
        return filedValue;
    }
}
